package edu.mapi.ir.log;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import edu.mapi.ir.gui.AudioClips;
import edu.mapi.ir.gui.GuiUtils;
import edu.mapi.ir.gui.ToolbarButton;
import edu.mapi.ir.gui.tablelayout.TableLayout;
import edu.mapi.ir.viewer.MazePanel;
import edu.mapi.ir.viewer.MousePlayer;
import edu.mapi.ir.viewer.ScoreWall;

/**
 * @author ZP
 */
public class ReplayPanel extends JPanel {

	private JLabel timeLabel = new JLabel("T:", JLabel.CENTER);
	private JSlider slider;
	private int curTime;
	private int millisBetweenUpdates = 50;
	public AbstractAction play, stop, rewind, fastForward;
	private Timer t = new Timer("replay timer");
	private static int PLAYING = 0, STOPPED = 1, NO_LOG = 2;
	private int curState = NO_LOG;
	private LogReplay logReplay;
	//private MazeViewer viewer;
	private MazePanel mazePanel;
	private ScoreWall scores;
	
	private boolean ignoreSliderChange = false;
	
	private TimerTask updaterTask() {
		TimerTask replayTask = new TimerTask() {
			
			public void run() {
				
				Vector<MousePlayer> state = logReplay.getStateAt(curTime++);
				if (state == null) {
					curTime = logReplay.getMinTime();
					curState = STOPPED;
					if (t != null) {
						t.cancel();
						t = null;
					}
					return;
				}
				ignoreSliderChange = true;
				slider.setValue(curTime);
				timeLabel.setText("T: "+curTime);
				if (!state.isEmpty()) {
					for (MousePlayer mp : state) {
						
						ReplayPanel.this.mazePanel.setMouse(mp);						
						ReplayPanel.this.scores.setMouse(mp);
					}					
				}						
			}
		};
		return replayTask;
	}
	
	public ReplayPanel(LogReplay replay, MazePanel mazePanel, ScoreWall scores) {
		
		this.logReplay = replay;
		this.scores = scores;
		this.mazePanel = mazePanel;
		
		setLayout(new TableLayout(new double[] {50, 25, 25, 25, 25, TableLayout.FILL, 50}, new double[] {25}));
		setBorder(BorderFactory.createLineBorder(Color.black, 3));
		curTime = replay.getMinTime();
		timeLabel.setText("T: "+curTime);
		slider = new JSlider(replay.getMinTime(), replay.getMaxTime(), curTime);
		slider.setMinorTickSpacing(1);
		add(timeLabel, "0,0");
		initActions();
		add(new ToolbarButton(play), "1,0");
		add(new ToolbarButton(stop), "2,0");
		add(new ToolbarButton(rewind), "3,0");
		add(new ToolbarButton(fastForward), "4,0");
		add(slider, "5,0");
		slider.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				if (ignoreSliderChange) {
					ignoreSliderChange = false;
					return;
				}
				curTime = slider.getValue();
				Vector<MousePlayer> state = logReplay.getStateAt(curTime);
				ReplayPanel.this.mazePanel.clearPaths();
				if (state != null) {
					for (MousePlayer mp : state) {
						ReplayPanel.this.mazePanel.setMouse(mp);						
						ReplayPanel.this.scores.setMouse(mp);
					}
				}
			}
		});
		
		Vector<MousePlayer> state = logReplay.getStateAt(curTime);
		ReplayPanel.this.mazePanel.updateLayers();
		if (state != null) {
			for (MousePlayer mp : state) {
				ReplayPanel.this.mazePanel.setMouse(mp);						
				ReplayPanel.this.scores.setMouse(mp);
			}
		}
	}
	
	private void initActions() {
		play = new AbstractAction("Play", new ImageIcon(GuiUtils.getImage("imgs/buttons/play.png"))) {
			public void actionPerformed(ActionEvent e) {
				if (t != null) {
					t.cancel();
					t = null;
				}
				millisBetweenUpdates = 60;
				
				curState = PLAYING;
				if (t != null)
					t.cancel();
				t = new Timer("Replay updater");
				t.scheduleAtFixedRate(updaterTask(), millisBetweenUpdates, millisBetweenUpdates);
				play.setEnabled(false);
				stop.setEnabled(true);
			}			
		};
		play.setEnabled(true);
		
		stop = new AbstractAction("Stop", new ImageIcon(GuiUtils.getImage("imgs/buttons/stop.png"))) {
			public void actionPerformed(ActionEvent e) {
				curState = STOPPED;
				if (t != null) {
					t.cancel();
					t = null;
				}
				stop.setEnabled(false);
				play.setEnabled(true);
			}
		};
		stop.setEnabled(false);
		
		rewind = new AbstractAction("Restart", new ImageIcon(GuiUtils.getImage("imgs/buttons/start.png"))) {
			public void actionPerformed(ActionEvent e) {
				mazePanel.updateLayers();				
				curTime = logReplay.getMinTime();
				
				Vector<MousePlayer> state = logReplay.getStateAt(curTime);
				mazePanel.clearPaths();				
				if (state != null) {
					for (MousePlayer mp : state) {
						ReplayPanel.this.mazePanel.setMouse(mp);						
						ReplayPanel.this.scores.setMouse(mp);
					}
						
				}
			}
		};
		
		fastForward = new AbstractAction("Fast Forward", new ImageIcon(GuiUtils.getImage("imgs/buttons/fwd.png"))) {
			public void actionPerformed(ActionEvent e) {
				if (t != null) {
					t.cancel();
					t = null;
				}
				t = new Timer("Replay updater");
				t.schedule(updaterTask(), 20, 20);
				play.setEnabled(true);
			}
		};
		
	}
	
}
